Exploratory Data Analysis

\(\hspace{0.3cm}\) More articles: \(\hspace{0.1cm}\) Estadistica4all

\(\hspace{0.3cm}\) Author: \(\hspace{0.1cm}\) Fabio Scielzo Ortiz

\(\hspace{0.3cm}\) If you use this article, please, reference it:

\(\hspace{0.5cm}\) Scielzo Ortiz, Fabio. (2023). Exploratory Data Analysis. http://estadistica4all.com/Articulos/EDA.html

It’s recommended open the article in a computer or tablet.


1 Exploratory Data Analysis (EDA)

Exploratory data analysis (análisis de datos exploratorio) hace referencia analisis estadistico, principalmente descriptivo, de un conjunto de datos.

A continuación se va a proponer una metodologia (unos pasos a seguir) para desarrollar un EDA.

A continuación cargamos el data-set al que vamos a aplicar un EDA

import pandas as pd

Netflix_Data = pd.read_csv('titles.csv')

Hacemos un head() del data-set para ver que pinta tiene:

Netflix_Data.head()
id title type description release_year age_certification runtime genres production_countries seasons imdb_id imdb_score imdb_votes tmdb_popularity tmdb_score
0 ts300399 Five Came Back: The Reference Films SHOW This collection includes 12 World War II-era p… 1945 TV-MA 51 [‘documentation’] [‘US’] 1.0 NaN NaN NaN 0.600 NaN
1 tm84618 Taxi Driver MOVIE A mentally unstable Vietnam War veteran works … 1976 R 114 [‘drama’, ‘crime’] [‘US’] NaN tt0075314 8.2 808582.0 40.965 8.179
2 tm154986 Deliverance MOVIE Intent on seeing the Cahulawassee River before… 1972 R 109 [‘drama’, ‘action’, ‘thriller’, ‘european’] [‘US’] NaN tt0068473 7.7 107673.0 10.010 7.300
3 tm127384 Monty Python and the Holy Grail MOVIE King Arthur, accompanied by his squire, recrui… 1975 PG 91 [‘fantasy’, ‘action’, ‘comedy’] [‘GB’] NaN tt0071853 8.2 534486.0 15.461 7.811
4 tm120801 The Dirty Dozen MOVIE 12 American military prisoners in World War II… 1967 NaN 150 [‘war’, ‘action’] [‘GB’, ‘US’] NaN tt0061578 7.7 72662.0 20.398 7.600


2 Esctructura del data-set

2.1 Tamaño

Lo primero es determinar el tamaño del data-set al que se le aplica el EDA. El tamaño de un data-set se puede concebir como su nº de filas y columnas.

Netflix_Data.shape
(5850, 15)

El data set tiene 5850 filas (observaciones) y 15 columnas (variables).

2.2 Descripción conceptual de las variables

Esta data-set contieene información sobre 15 variables para 5850 títulos de Netflix.

La siguiente tabla contiene una breve descripción de las variables del data-set:

Variable Descripción Tipo
id The title ID on JustWatch Identificador
title The name of the title Texto
type TV show or movie Categórica
description A brief description Texto
release_year Año de lanzamiento Cuantitativa
age_certification La calificación de edad Categórica
runtime el nº de episiodios (show), el tiempo de durancion en minutos (movie) Cuantitativa
genres A list of genres Categórica
production_countries A list of countries that produced the title Categórica
seasons Number of seasons if it’s a SHOW Cuantitativa
imdb_id The title ID on IMDB Identificador
imdb_score Puntuación en IMDB Cuantitativa
imdb_votes nº de votos en IMDB Cuantitativa
tmdb_popularity Popularity on TMDB Cuantitativa
tmdb_score Puntuación en TMDB Cuantitativa


2.3 Tipo de variables

Ahora vamos a ver de que tipo son cada una de las 15 variables en Python

Netflix_Data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5850 entries, 0 to 5849
Data columns (total 15 columns):
 #   Column                Non-Null Count  Dtype  
---  ------                --------------  -----  
 0   id                    5850 non-null   object 
 1   title                 5849 non-null   object 
 2   type                  5850 non-null   object 
 3   description           5832 non-null   object 
 4   release_year          5850 non-null   int64  
 5   age_certification     3231 non-null   object 
 6   runtime               5850 non-null   int64  
 7   genres                5850 non-null   object 
 8   production_countries  5850 non-null   object 
 9   seasons               2106 non-null   float64
 10  imdb_id               5447 non-null   object 
 11  imdb_score            5368 non-null   float64
 12  imdb_votes            5352 non-null   float64
 13  tmdb_popularity       5759 non-null   float64
 14  tmdb_score            5539 non-null   float64
dtypes: float64(5), int64(2), object(8)
memory usage: 685.7+ KB

El Dtype object es el típico de variables categoricas, identificadores o texto.

El Dtype float64 y int64 es típico de variables cuantitativas (continuas y discretas, respectivamente).


2.4 Valores faltantes (NA)

Ahora vamos a calcular la proporcion de valores faltantes sobre el total de datos, para cada una de las variables:

Prop_NA = Netflix_Data.isnull().sum() / len(Netflix_Data)

Prop_NA
id                      0.000000
title                   0.000171
type                    0.000000
description             0.003077
release_year            0.000000
age_certification       0.447692
runtime                 0.000000
genres                  0.000000
production_countries    0.000000
seasons                 0.640000
imdb_id                 0.068889
imdb_score              0.082393
imdb_votes              0.085128
tmdb_popularity         0.015556
tmdb_score              0.053162
dtype: float64


Podemos ver que hay variables como age_certification con una alta proporción de valores faltantes (44.77%).

seasonsería la variable con mayor proporción de valores faltantes, pero esto se debe a que solo esta definida para las series (type=SHOW)

En este artículo no se hará un tratamiento de los valores faltantes, el cual será expuesto en un futuro articulo sobre pre-procesamiento de datos.

3 Descripción Estadistica Básica

A continuación vamos a realizar una descripción estadistica básica de las variables, a traves de dicersos estadisticos básicos.

3.1 Estadisticos básicos para las variables cuantitativas

Para las variables cuantitativas:

Netflix_Data.describe()
release_year runtime seasons imdb_score imdb_votes tmdb_popularity tmdb_score
count 5850.000000 5850.000000 2106.000000 5368.000000 5.352000e+03 5759.000000 5539.000000
mean 2016.417094 76.888889 2.162868 6.510861 2.343938e+04 22.637925 6.829175
std 6.937726 39.002509 2.689041 1.163826 9.582047e+04 81.680263 1.170391
min 1945.000000 0.000000 1.000000 1.500000 5.000000e+00 0.009442 0.500000
25% 2016.000000 44.000000 1.000000 5.800000 5.167500e+02 2.728500 6.100000
50% 2018.000000 83.000000 1.000000 6.600000 2.233500e+03 6.821000 6.900000
75% 2020.000000 104.000000 2.000000 7.300000 9.494000e+03 16.590000 7.537500
max 2022.000000 240.000000 42.000000 9.600000 2.294231e+06 2274.044000 10.000000


3.2 Estadisticos básicos para las variables categóricas

Para las variables categóricas (no cuantitativas, en general) :

Netflix_Data.loc[: , ['title', 'description', 'age_certification', 'genres', 'production_countries' ]].describe()
title description age_certification genres production_countries
count 5849 5832 3231 5850 5850
unique 5798 5829 11 1726 452
top The Gift Five families struggle with the ups and downs … TV-MA [‘comedy’] [‘US’]
freq 3 2 883 484 1959


3.3 Gráficos conjuntos para las variables cuantitativas

En esta seccion vamos a hacer un analisis gráfico básico de las variables cuantitativas, consideradas de manera conjunta.

Cargamos las librerias necesarias para los gráficos:

import numpy as np

import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt

3.3.1 Histograma conjunto de las variables cuantitativas

Vamos a generar un grafico con un histograma para cada una de las variables cuantitativas:

fig, axs = plt.subplots(3, 3, figsize=(11, 11))

p1 = sns.histplot(data=Netflix_Data, x="release_year", stat="proportion", bins=15, color="skyblue", ax=axs[0, 0])
 

p2 = sns.histplot(data=Netflix_Data, x="runtime", stat="proportion", bins=15, color="olive", ax=axs[0, 1])
p2.axes.set(xlabel='runtime', ylabel=' ')
 

p3 = sns.histplot(data=Netflix_Data, x="seasons", stat="proportion", bins=15, color="blue", ax=axs[0, 2])
p3.axes.set(xlabel='seasons', ylabel=' ')
 

p4 = sns.histplot(data=Netflix_Data, x="imdb_score", stat="proportion", bins=15, color="teal", ax=axs[1, 0])
p4.axes.set(xlabel='imdb_score', ylabel=' ')
 

p5 = sns.histplot(data=Netflix_Data, x="imdb_votes", stat="proportion", bins=15, color="purple", ax=axs[1, 1])
p5.axes.set(xlabel='imdb_votes', ylabel=' ')
 

p6 = sns.histplot(data=Netflix_Data, x="tmdb_popularity", stat="proportion", bins=15, color="pink", ax=axs[1, 2])
p6.axes.set(xlabel='tmdb_popularity', ylabel=' ')
 
 
p7 = sns.histplot(data=Netflix_Data, x="tmdb_score", stat="proportion", bins=15, color="red", ax=axs[2, 0])
p7.axes.set(xlabel='tmdb_score', ylabel=' ')
 
fig.savefig('p1.png', format='png', dpi=1200)

plt.show()


Histograma conjunto de las variables cuantitativas


3.3.2 Box-Plot conjunto de las variables cuantitativas

Vamos a generar un grafico con un box-plot para cada una de las variables cuantitativas:

fig, axs = plt.subplots(3, 3, figsize=(11, 11))

p1 = sns.boxplot(data=Netflix_Data, x="release_year", color="skyblue", ax=axs[0, 0])
 

p2 = sns.boxplot(data=Netflix_Data, x="runtime",  color="olive", ax=axs[0, 1])
p2.axes.set(xlabel='runtime', ylabel=' ')
p2.set_xticks( range(int(Netflix_Data['runtime'].min()) , int(Netflix_Data['runtime'].max()) , 100) )
p2.set_yticks( np.arange(0, 1, 0.1)  )

p3 = sns.boxplot(data=Netflix_Data, x="seasons", color="blue", ax=axs[0, 2])
p3.axes.set(xlabel='seasons', ylabel=' ')
 

p4 = sns.boxplot(data=Netflix_Data, x="imdb_score", color="teal", ax=axs[1, 0])
p4.axes.set(xlabel='imdb_score', ylabel=' ')
p4.set_xticks( range(int(Netflix_Data['imdb_score'].min()) , int(Netflix_Data['imdb_score'].max()) , 300) )
p4.set_yticks( np.arange(0, 1, 0.1)  )

p5 = sns.boxplot(data=Netflix_Data, x="imdb_votes", color="purple", ax=axs[1, 1])
p5.axes.set(xlabel='imdb_votes', ylabel=' ')
p5.set_xticks( range(int(Netflix_Data['imdb_votes'].min()) , int(Netflix_Data['imdb_votes'].max()/2) , 500000) )
p5.set_yticks( np.arange(0, 1, 0.1)  )

p6 = sns.boxplot(data=Netflix_Data, x="tmdb_popularity", color="pink", ax=axs[1, 2])
p6.axes.set(xlabel='tmdb_popularity', ylabel=' ')
p6.set_xticks( range(int(Netflix_Data['tmdb_popularity'].min()) , int(Netflix_Data['tmdb_popularity'].max()+1) , 1000) )
p6.set_yticks( np.arange(0, 1, 0.1)  )
 
p7 = sns.boxplot(data=Netflix_Data, x="tmdb_score", color="red", ax=axs[2, 0])
p7.axes.set(xlabel='tmdb_score', ylabel=' ')
p7.set_xticks( range(int(Netflix_Data['tmdb_score'].min()) , int(Netflix_Data['tmdb_score'].max()+1) , 2) )
p7.set_yticks( np.arange(0, 1, 0.1)  )

plt.show()


Box-Plot conjunto de las variables cuantitativas


3.3.3 Empirical-Cumulative-Distribution-Function-Plot conjunto de las variables cuantitativas

Vamos a generar un grafico con un ECDF-plot para cada una de las variables cuantitativas:

fig, axs = plt.subplots(3, 3, figsize=(11, 11))

p1 = sns.ecdfplot(data=Netflix_Data, x="release_year", color="skyblue", ax=axs[0, 0])
p1.set_xticks( range(int(Netflix_Data['release_year'].min()) , int(Netflix_Data['release_year'].max()+20) , 20) )
p1.set_yticks( np.arange(0, 1, 0.1)  )

p2 = sns.ecdfplot(data=Netflix_Data, x="runtime",  color="olive", ax=axs[0, 1])
p2.axes.set(xlabel='runtime', ylabel=' ')
p2.set_xticks( range(int(Netflix_Data['runtime'].min()) , int(Netflix_Data['runtime'].max()) , 100) )
p2.set_yticks( np.arange(0, 1, 0.1)  )

p3 = sns.ecdfplot(data=Netflix_Data, x="seasons", color="blue", ax=axs[0, 2])
p3.axes.set(xlabel='seasons', ylabel=' ')
p3.set_xticks( range(int(Netflix_Data['seasons'].min()) , int(Netflix_Data['seasons'].max()) , 4) )
p3.set_yticks( np.arange(0, 1, 0.1)  )

p4 = sns.ecdfplot(data=Netflix_Data, x="imdb_score", color="teal", ax=axs[1, 0])
p4.axes.set(xlabel='imdb_score', ylabel=' ')
p4.set_xticks( range(int(Netflix_Data['imdb_score'].min()) , int(Netflix_Data['imdb_score'].max()) , 300) )
p4.set_yticks( np.arange(0, 1, 0.1)  )

p5 = sns.ecdfplot(data=Netflix_Data, x="imdb_votes", color="purple", ax=axs[1, 1])
p5.axes.set(xlabel='imdb_votes', ylabel=' ')
p5.set_xticks( range(int(Netflix_Data['imdb_votes'].min()) , int(Netflix_Data['imdb_votes'].max()/2) , 500000) )
p5.set_yticks( np.arange(0, 1, 0.1)  )

p6 = sns.ecdfplot(data=Netflix_Data, x="tmdb_popularity", color="pink", ax=axs[1, 2])
p6.axes.set(xlabel='tmdb_popularity', ylabel=' ')
p6.set_xticks( range(int(Netflix_Data['tmdb_popularity'].min()) , int(Netflix_Data['tmdb_popularity'].max()+1) , 1000) )
p6.set_yticks( np.arange(0, 1, 0.1)  )
 
p7 = sns.ecdfplot(data=Netflix_Data, x="tmdb_score", color="red", ax=axs[2, 0])
p7.axes.set(xlabel='tmdb_score', ylabel=' ')
p7.set_xticks( range(int(Netflix_Data['tmdb_score'].min()) , int(Netflix_Data['tmdb_score'].max()+1) , 50) )
p7.set_yticks( np.arange(0, 1, 0.1)  )

plt.show()


ECDF-Plot conjunto de las variables cuantitativas


3.4 Gráficos conjuntos para las variables categoricas

3.4.1 Bar-plot conjunto de las variables categóricas

Vamos a generar un grafico con un bar-plot para cada una de las variables categóricas, excepto para aquellas cuyo nº de categorias es excesivo, y por tanto no es práctico el gráfico:

fig, axs = plt.subplots(1, 2, figsize=(13, 6))

p1 = sns.countplot(x='type', data=Netflix_Data, ax=axs[0]) 
p1.set_xticklabels(['Movie', 'Show'])
p1.axes.set(xlabel='type', ylabel='count')

p2 = sns.countplot(x='age_certification', data=Netflix_Data, ax=axs[1]) 

plt.show()


Bar-Plot conjunto de variables categoricas


4 Análisis Estadístico

En la sección anterior se hizo una descripción estadistica básica de las variables del data-set con el que estamos trabajando, pero no se ha hecho ningun analisis de los resultados obtenidos.

En esta seccion además de ampliar la descripción estadistica de los datos, se llevará a cabo un analisis de los resultados obtenidos.


4.1 Estadisticos para las variables cuantitativas

4.2 Estadisticos para las variables categoricas

4.3 Tablas de frecuencias

4.4 Gráficos individuales para las variables cuantitativas

4.5 Gráficos individuales para las variables categoricas